
/*
 *  Copyright 2021
 *
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * SPDX-License-Identifier: GPL-3.0+
 * License-Filename: LICENSE
 */

#include "config.h"

#include <stdio.h>
#include <string.h>
#include <zlib.h>

#include "splay-tree.h"
#include "main.h"
#include "dp.h"
#include "dpmisc.h"
#include "lex.yy.h"
#include "sfg.h"

static int dpif(void);

char parsermessage[256];

int main(int argc, char *argv[])
{
	gzFile f = (gzFile) 0;
	int status = 0;

	/* this is a demo how the parser can be used with GNU GPL graph layout software as a dot alternative */
	printf("%s(): yadot yet-another-dot GNU GPL Free software dot alike program demo\n", __func__);

	/* handle command line options */
	if (argc == 1) {
		/* no filename */
		printf("%s(): need one input file\n", __func__);
		/* or here code to read from stdin */
		return (0);
	} else {
		/* use input file */
		f = gzopen(argv[1], "r");
	}

	/* use test file. */
	if (f == (gzFile) 0) {
		printf("%s(): cannot open file %s\n", __func__, argv[1]);
		return (0);
	}

	dp_lex_init(f, 0 /* 1 for debug */);
	status = yyparse();
	dp_lex_deinit();
	printf("main() %d status `%s'\n", status, dp_errmsg);
	fflush(stdout);
	if (status == 0) {
		status = dp_datachk();
	}
	printf("%s: parse status %d `%s' [status 0 means everything oke]\n", __func__, status, dp_errmsg);

	/* copy the parsed data */
	status = dpif();

	dp_clearall();
	gzclose(f);

	if (status == 1) {
		printf("%s(): parsed data error of inputfile %s\n", __func__, argv[1]);
		return (0);
	}

	if (status == 2) {
		printf("%s(): parsed data has no nodes in inputfile %s\n", __func__, argv[1]);
		return (0);
	}

	if (status == 3) {
		printf("%s(): sfg error with parsed data in inputfile %s\n", __func__, argv[1]);
		return (0);
	}

	/* status = 0, graph layout is successfully done. */
	printf("\n%s(): now run drawing routines to generate svg, png, jpg or other drawing\n",__func__);

	/* here the drawing routines, see sfg.c */

	return (0);
}

/* copy parsed data into layouter */
static int dpif(void)
{
	struct dpnlink *nss = NULL;
	struct dpnode *node = NULL;
	struct dpedge *edge = NULL;
	struct dpelink *es = NULL;
	char *nodename = NULL;
	int nch = 0;
	int nn = 0;
	int ne = 0;
	int status = 0;

	printf("%s(): handling parsed data\n", __func__);

	if (!dp_groot) {
		return (1);
	}

	if (!dp_anodes) {
		return (2);
	}

	/* init to start */
	status = sfg_init();
	if (status < 0) {	/* error */
		return (3);
	}

	/* list with all nodes */
	ne = 1;			/* edge number */
	nss = dp_anodes;
	while (nss) {
		printf(".");

		/* get node data */
		node = nss->n;

		/* node base name */
		nodename = node->name;

		/* node optional label */
		if (nss->n->label) {
			nodename = nss->n->label;
		}

		/* node should have a name now. */
		if (!nodename) {
			/* set some node name and should not happen */
			nodename = ".";
		}

		nch = strlen(nodename);

		/* get uniq node number. */
		nn = node->nr;
		/* must start at 1 */
		nn++;

		status = sfg_addnode(nn, nch * 25, 20);

		if (status < 0) {	/* error */
			printf("addnode %d error %d\n", nn, status);
			return (3);
		}

		/* to next node. */
		nss = nss->next;
	}

	/* add all edges */
	es = dp_aedges;

	while (es) {
		edge = es->e;
		printf("+");

		if (!edge->fn) {
			printf("nil edge fn\n");
			return (3);
		}

		if (!edge->tn) {
			printf("nil edge tn\n");
			return (3);
		}

		/* edge without edge label */
		status = sfg_addedge(ne, /* from */ edge->fn->nr + 1, /* to */ edge->tn->nr + 1, 0, 0);
		if (status < 0) {	/* error */
			printf("addedge %d error %d\n", ne, status);
		}

		ne++;
		es = es->next;
	}

	/* set min (x,y) spacing of nodes */
	status = sfg_xspacing(5);
	if (status < 0) {	/* error */
		printf("xspacing error\n");
		return (3);
	}

	status = sfg_yspacing(15);
	if (status < 0) {	/* error */
		printf("yspacing error\n");
		return (3);
	}

	printf("\n%s(): creating graph layout image\n", __func__);

	/* run layout */
	status = sfg_layout();
	if (status < 0) {	/* error */
		printf("layouter error\n");
		return (3);
	}

	printf("%s(): layouted graph drawing has size (%d,%d) with %d levels\n", __func__, sfg_maxx(), sfg_maxy(), sfg_nlevels());

	return (0);
}

/* end */
